package com.seguriapp.social;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;

import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.User;
import twitter4j.http.AccessToken;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Window;

import com.seguriapp.R;
import com.seguriapp.dialogs.TwitterDialog;
import com.seguriapp.dialogs.TwitterMessageDialog;
import com.seguriapp.sync.TwitterTask;

/*
 Copyright [2010] [Abhinava Srivastava]

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
//TODO: check this class, comments, ways of handling exceptions, and the necessary javadoc 
public class TwitterApp {
	private final Twitter mTwitter;
	private final TwitterSession mSession;
	private AccessToken mAccessToken;
	private final CommonsHttpOAuthConsumer mHttpOauthConsumer;
	private final OAuthProvider mHttpOauthprovider;
	private final String mConsumerKey;
	private final String mSecretKey;
	private ProgressDialog mProgressDlg;
	private TwDialogListener mListener;
	private Activity context;
	private int mMode;

	public static final int EXPLICIT_MODE = 10;
	public static final int IMPLICIT_MODE = 11;

	public static final String CALLBACK_URL = "SeguriApp://twitt";
	private static final String TWITTER_ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
	private static final String TWITTER_AUTHORZE_URL = "https://api.twitter.com/oauth/authorize";
	private static final String TWITTER_REQUEST_URL = "https://api.twitter.com/oauth/request_token";
	public static final String MESSAGE = "There is lot more to come, Subscribe to http://abhinavasblog.blogspot.com";

	public TwitterApp(final Activity context, final String entityToShare,
			final int mode) {
		this.context = context;
		mMode = mode;
		mTwitter = new TwitterFactory().getInstance();
		mSession = new TwitterSession(context);
		mProgressDlg = new ProgressDialog(context);

		mProgressDlg.requestWindowFeature(Window.FEATURE_NO_TITLE);

		mConsumerKey = context.getString(R.string.twitterConsumerKey);
		mSecretKey = context.getString(R.string.twitterSecretKey);

		mHttpOauthConsumer = new CommonsHttpOAuthConsumer(mConsumerKey,
				mSecretKey);

		final String request_url = TWITTER_REQUEST_URL;
		final String access_token_url = TWITTER_ACCESS_TOKEN_URL;
		final String authorize_url = TWITTER_AUTHORZE_URL;

		mHttpOauthprovider = new DefaultOAuthProvider(request_url,
				access_token_url, authorize_url);
		mAccessToken = mSession.getAccessToken();

		configureToken();

		setListener(new TwDialogListener() {

			public void onError(final String value) {
				Log.e("Twitter error", value);
				resetAccessToken();
			}

			public void onComplete(final String value) {
				try {
					shareInTwitter(entityToShare);

				} catch (Exception e) {
					Log.e("twitter error", e.getMessage());
				}
			}
		});
	}

	public void setListener(final TwDialogListener listener) {
		mListener = listener;
	}

	@SuppressWarnings("deprecation")
	private void configureToken() {
		if (mAccessToken != null) {
			mTwitter.setOAuthConsumer(mConsumerKey, mSecretKey);
			mTwitter.setOAuthAccessToken(mAccessToken);
		}
	}

	public boolean hasAccessToken() {
		return (mAccessToken == null) ? false : true;
	}

	public void resetAccessToken() {
		if (mAccessToken != null) {
			mSession.resetAccessToken();

			mAccessToken = null;
		}
	}

	public String getUsername() {
		return mSession.getUsername();
	}

	public void authorize() {
		mProgressDlg.setMessage("Initializing ...");
		mProgressDlg.show();

		new Thread() {
			@Override
			public void run() {
				String authUrl = "";
				int what = 1;

				try {
					authUrl = mHttpOauthprovider.retrieveRequestToken(
							mHttpOauthConsumer, CALLBACK_URL);
					what = 0;
				} catch (Exception e) {
					Log.e("authorize", e.getMessage());
					// e.printStackTrace();
				}
				mHandler.sendMessage(mHandler
						.obtainMessage(what, 1, 0, authUrl));

			}
		}.start();
	}

	public void processToken(final String callbackUrl) {
		mProgressDlg.setMessage("Finalizing ...");
		mProgressDlg.show();

		final String verifier = getVerifier(callbackUrl);

		new Thread() {
			@Override
			public void run() {
				int what = 1;

				try {
					mHttpOauthprovider.retrieveAccessToken(mHttpOauthConsumer,
							verifier);

					mAccessToken = new AccessToken(
							mHttpOauthConsumer.getToken(),
							mHttpOauthConsumer.getTokenSecret());

					configureToken();

					final User user = mTwitter.verifyCredentials();

					mSession.storeAccessToken(mAccessToken, user.getName());

					what = 0;
					mHandler.sendMessage(mHandler.obtainMessage(what, 2, 0));
				} catch (Exception e) {
					Log.e("processToken", e.getMessage());
					this.run();
					// e.printStackTrace();
				}

			}
		}.start();
		// new TwitterMessageDialog(context, mTwitter, message).show();
	}

	private String getVerifier(String callbackUrl) {
		String verifier = "";

		try {
			callbackUrl = callbackUrl.replace("SeguriApp", "http");

			final URL url = new URL(callbackUrl);
			final String query = url.getQuery();

			final String array[] = query.split("&");

			for (String parameter : array) {
				String v[] = parameter.split("=");

				if (URLDecoder.decode(v[0]).equals(
						oauth.signpost.OAuth.OAUTH_VERIFIER)) {
					verifier = URLDecoder.decode(v[1]);
					break;
				}
			}
		} catch (MalformedURLException e) {
			Log.e("Twitter MalformedURLException", e.getMessage());
		}

		return verifier;
	}

	private void showLoginDialog(final String url) {
		final TwDialogListener listener = new TwDialogListener() {

			public void onComplete(final String value) {
				processToken(value);
			}

			public void onError(final String value) {
				mListener.onError("Failed opening authorization page");
			}
		};

		new TwitterDialog(context, url, listener).show();
	}

	private final Handler mHandler = new Handler() {
		@Override
		public void handleMessage(final Message msg) {
			mProgressDlg.dismiss();

			if (msg.what == 1) {
				if (msg.arg1 == 1) {
					mListener.onError("Error getting request token");
				} else {
					mListener.onError("Error getting access token");
				}
			} else {
				if (msg.arg1 == 1) {
					showLoginDialog((String) msg.obj);
				} else {
					mListener.onComplete("");
				}
			}
		}
	};

	public interface TwDialogListener {
		public void onComplete(String value);

		public void onError(String value);
	}

	public void shareInTwitter(final String entityToShare) {

		if (hasAccessToken()) {
			String message = "";
			final StringBuilder newStatus = new StringBuilder(message);

			newStatus.append(entityToShare);
			// newStatus.append("http://maps.google.com/maps?msid=204407220294418886204.0004ae95d48a18fc9ce3b&msa=0&ll=-12.0753441,-77.09072063&spn=0.00417,0.006089&t=h&z=18");
			// newStatus.append(String.format("http://maps.google.com/maps?msid=204407220294418886204.0004ae95d48a18fc9ce3b&msa=0&ll=%f,%f"
			// +
			// "&spn=0.00417,0.006089&t=h&z=18&vpsrc=6&iwloc=0004ae95d9727605b99d2",
			// feedEnt.mLatitude, feedEnt.mLongitude ));

			message = newStatus.toString();
			if (mMode == EXPLICIT_MODE) {
				new TwitterMessageDialog(context, mTwitter, message).show();
			} else {
				final TwitterTask dataTask = new TwitterTask(context, mTwitter);
				dataTask.execute(message);
			}

		} else {
			authorize();
		}
	}
}